package cn.rkylin.oms.salespromotion.rules.util.stretegy;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.util.BeanUtil;

import cn.rkylin.apollo.common.util.BeanUtils;
import cn.rkylin.oms.common.consts.YesNoConst;
import cn.rkylin.oms.item.service.IEcSkuGroupService;
import cn.rkylin.oms.order.domain.OrderSku;
import cn.rkylin.oms.order.service.IOrderService;
import cn.rkylin.oms.order.vo.OrderSkuVO;
import cn.rkylin.oms.order.vo.OrderVO;
import cn.rkylin.oms.salespromotion.rules.domain.SalesPromotionGift;
import cn.rkylin.oms.salespromotion.rules.vo.SalesPromotionRuleVO;

public abstract class AbstractGiftCaculateStretegy extends SpringBeanAutowiringSupport implements IGiftCaculateStretegy {
    /**
     * 订单金额
     */
    public static String CACULATE_BY_ORDER_AMOUNT = "coin";
    /**
     * 商品种类数
     */
    public static String CACULATE_BY_GOODS_KIND = "kind";
    /**
     * 商品件数
     */
    public static String CACULATE_BY_GOODS_PIECE = "piece";
    /**
     * 订单次序
     */
    public static String CACULATE_BY_ORDER_TIMES = "times";

    private RedisTemplate<Serializable, Serializable> redisTemplate = BeanUtils.getBean("redisTemplate");
    
    @Autowired
    private IEcSkuGroupService ecSkuGroupService = BeanUtils.getBean("ecSkuGroupService");
    @Autowired
    private IOrderService orderService = BeanUtils.getBean("orderService");

    /**
     * 计算赠品以及赠送数量： <br/>
     * 1. 买就送 <br/>
     * 2. 满就送 <br/>
     * 3. 多买多送 <br/>
     * 4. 分段赠送 <br/>
     * @throws Exception 
     * 
     * @see cn.rkylin.oms.salespromotion.rules.util.stretegy.IGiftCaculateStretegy#getGifts(cn.rkylin.oms.salespromotion.rules.vo.SalesPromotionRuleVO,
     *      cn.rkylin.oms.order.vo.OrderVO)
     */
    @Override
    public List<Map<String, Object>> getGifts(SalesPromotionRuleVO ruleVO, OrderVO order) throws Exception {
        List<Map<String, Object>> giftList = new ArrayList<Map<String, Object>>();
        JSONObject ruleObj = JSONObject.parseObject(ruleVO.getPresentCaculateRule());
        JSONArray segments = ruleObj.getJSONArray("segments");
        String sendType = ruleObj.getString("sendType");

        List<OrderSku> skuList = order.getSysOrderGoodsList();
        if(skuList==null||skuList.size()==0) {
            List<OrderSkuVO> skuVOList = orderService.getOrderSku(order.getOrderId());
            List<OrderSku> skuListDemp = new ArrayList<OrderSku>();
            for (OrderSkuVO orderSkuVO : skuVOList) {
                OrderSku temp = new OrderSku();
                org.springframework.beans.BeanUtils.copyProperties(orderSkuVO, temp);
                skuListDemp.add(temp);
            }
            order.setSysOrderGoodsList(skuListDemp);
            skuList = order.getSysOrderGoodsList();
        }
        
        // 买就送或者满就送
        if ("buySend".equalsIgnoreCase(sendType) || "fullSend".equalsIgnoreCase(sendType)) {
            // 如果组合商品不参与，则从订单商品列表中去掉组合商品
            if(YesNoConst.NO.equalsIgnoreCase(ruleObj.getString("isGroupEnvolve"))) {
                removeGroupSku(order);
            }
            if(order.getSysOrderGoodsList().size()>0) {
                BigDecimal cacuNum = getCaculateNum(ruleVO, order); // 订单总件数／种类数／次数／金额数
                
                JSONObject segment = segments.getJSONObject(0);
                // 根据数值和步长，计算赠送次数
                BigDecimal step = segment.getBigDecimal("limitEnd");
                int sendTimes = cacuNum.divide(step,2).intValue();    // 赠送次数
                
                if (sendTimes > 0) {
                    // 如果赠送次数大于0，才计算赠品列表
                    if (YesNoConst.NO.equals(ruleObj.getString("isMultiCount"))) {
                        // 如果不是多买多送，则赠送次数总是1
                        sendTimes = 1;
                    }
                    
                    // 计算赠品列表
                    if ("setSend".equalsIgnoreCase(ruleObj.getString("giftType"))) {
                        // 整组赠送
                        giftList = getGiftListInSet(sendTimes, ruleVO);
                    } else if ("prioritySend".equalsIgnoreCase(ruleObj.getString("giftType"))) {
                        // 按照优先级赠送
                        giftList = getGiftListByPriority(sendTimes, ruleVO);
                    }
                }
            }
        }

        // 返回赠品列表
        return giftList;
    }

    /**
     * removeGroupSku:从订单商品列表中移除组合商品. <br/>
     *
     * @author zhanghao
     * @param ruleObj
     * @throws Exception 
     */
    private void removeGroupSku(OrderVO order) throws Exception {
        List<OrderSku> skuList = order.getSysOrderGoodsList();
//        if(skuList==null||skuList.size()==0) {
//            List<OrderSkuVO> skuVOList = orderService.getOrderSku(order.getOrderId());
//            List<OrderSku> skuListDemp = new ArrayList<OrderSku>();
//            for (OrderSkuVO orderSkuVO : skuVOList) {
//                OrderSku temp = new OrderSku();
//                org.springframework.beans.BeanUtils.copyProperties(orderSkuVO, temp);
//                skuListDemp.add(temp);
//            }
//            order.setSysOrderGoodsList(skuListDemp);
//            skuList = order.getSysOrderGoodsList();
//        }
//        for (int i=0,j=skuList.size();i<j;i++) {
//            OrderSku orderSku = skuList.get(i);
//            if(ecSkuGroupService.getEcSkuGroupByEcSkuId(orderSku.getEcSkuId()).size()>0) {
//                ArrayUtils.remove(skuList, i);
//            }
//        }
        
        Iterator<OrderSku> iterator = skuList.iterator();
        while(iterator.hasNext()) {
            OrderSku orderSku = iterator.next();
            if(ecSkuGroupService.getEcSkuGroupByEcSkuId(orderSku.getEcSkuId()).size()>0) {
                iterator.remove();
            }
        }
    }

    /**
     * 按照优先级取得赠品列表中的赠品
     * 
     * @param times 需要赠送的次数
     * @return
     */
    private List<Map<String, Object>> getGiftListByPriority(int times, SalesPromotionRuleVO ruleVO) {
        List<Map<String, Object>> returnValue = new ArrayList<Map<String, Object>>();
        String ruleKey = ruleVO.getRuleId();
        Integer result = (Integer) redisTemplate.opsForValue().get(ruleKey);    // 缓存规则的已经赠送次数
        if(result==null) {
            result = 0;
        }
        int hasSendCount = result;  // 已经赠送出的商品数
        List<SalesPromotionGift> giftList = ruleVO.getGiftList();

        // 在查询时，就将赠品列表中的商品按照优先级升序排列了，次数按照优先级从高到低排序
        int needSendTimes = times; // 需要赠送的次数
        int levelHasSendCountTemp = hasSendCount;   // 缓存某阶段的已经赠送次数
        for (SalesPromotionGift salesPromotionGift : giftList) {
            int defaultPresentNum = salesPromotionGift.getDefaultPresentNum();  // 默认赠送数
            
            /*
             *  如果某优先级的可赠送次数，小于缓存的已经赠送次数，表示本阶段商品已经赠完<br/>
             *  此时就将已经赠送次数的缓存更新，并继续进行计算
             */
            
            if(salesPromotionGift.getPresentAmount()/defaultPresentNum<=levelHasSendCountTemp) {    // 已经赠送次数
                levelHasSendCountTemp -= Integer.valueOf(salesPromotionGift.getPresentAmount()/defaultPresentNum);
                continue;
            }else {
                // 计算该优先级下的赠品赠送数
                Integer thisTimes = getLevelSendCount(salesPromotionGift, needSendTimes,levelHasSendCountTemp); // 计算本次赠送次数
                Map<String, Object> tempMap = generateReturnGiftItem(salesPromotionGift.getRelGoodsSkuId(),
                        thisTimes * salesPromotionGift.getDefaultPresentNum());     // 本次本优先级赠送数
                returnValue.add(tempMap);
                needSendTimes = needSendTimes - thisTimes;
                if (needSendTimes <= 0) {
                    break;
                }
            }
        }
        redisTemplate.opsForValue().set(ruleKey, hasSendCount+times);
        return returnValue;
    }

    /**
     * getLevelSendCount:计算某优先级的商品的赠送次数. <br/>
     *
     * @author zhanghao
     * @param salesPromotionGift
     *            赠品信息
     * @param times
     *            剩余需要赠送的次数
     * @return
     */
    private int getLevelSendCount(SalesPromotionGift salesPromotionGift, int leftTimes,int levelHasSendCountTemp) {
        int returnValue = 0;
        int levelAmount = salesPromotionGift.getPresentAmount() / salesPromotionGift.getDefaultPresentNum(); // 计算优先级总共可赠送次数
        levelAmount = levelAmount - levelHasSendCountTemp; // 计算优先级下剩余可赠送次数
        if (levelAmount >= leftTimes) {
            // 如果剩余可赠送次数大于剩余需要赠送的次数，则返回剩余需要赠送的次数
            returnValue = leftTimes;
        } else {
            // 如果剩余可赠送次数小于等于剩余需要赠送的次数，则返回剩余可赠送的次数
            returnValue = levelAmount;
        }
        return returnValue;
    }

    /**
     * 成套取出赠品列表中的赠品
     * 
     * @param times
     * @return
     */
    private List<Map<String, Object>> getGiftListInSet(int times, SalesPromotionRuleVO ruleVO) {
        List<SalesPromotionGift> giftList = ruleVO.getGiftList();
        List<Map<String, Object>> returnValue = new ArrayList<Map<String, Object>>();
        if (giftList.size() > 0) {
            for (SalesPromotionGift salesPromotionGift : giftList) {
                Map<String, Object> tempMap = new HashMap<String, Object>();
                tempMap.put("skuId", salesPromotionGift.getRelGoodsSkuId()); // 商品SkuId
                tempMap.put("sendCount", salesPromotionGift.getDefaultPresentNum() * times); // 赠送数量
                returnValue.add(tempMap);
            }

        }
        return returnValue;
    }

    /**
     * getGiftListInSegment:按照每满赠送赠品. <br/>
     *
     * @author zhanghao
     * @param times
     * @param segment
     * @return
     */
    private List<Map<String, Object>> getGiftListInSegment(int times, JSONObject segment) {
        List<Map<String, Object>> returnList = new ArrayList<Map<String, Object>>();
        JSONArray giftArray = segment.getJSONArray("giftList");
        for (Object giftObject : giftArray) {
            JSONObject giftJSONObject = (JSONObject) giftObject;
            Map<String, Object> mapItem = generateReturnGiftItem(giftJSONObject.getString("skuId"),
                    giftJSONObject.getIntValue("number") * times);
            returnList.add(mapItem);
        }

        return returnList;
    }

    /**
     * 获取计算数值 例如： 1. 对按照次数计算的规则，则获取本促销规则下订单的次数 2.
     * 对于按照件数计算的规则，则获取本订单中商品的件数（如果只计算限制商品，则返回限制商品的件数） 3.
     * 对于按照种类计算的规则，则获取本订单中商品的种类数目（限制商品条件下，同上） 4.
     * 对于按照订单金额计算的规则，则获取本订单的总金额（限制商品条件下，同上）
     * 
     * @return
     */
    protected abstract BigDecimal getCaculateNum(SalesPromotionRuleVO ruleVO, OrderVO order);

    /**
     * generateReturnGiftItem:生成一条返回的赠品条目. <br/>
     *
     * @author zhanghao
     * @param skuId
     * @param sendCount
     * @return
     */
    private Map<String, Object> generateReturnGiftItem(String skuId, int sendCount) {
        Map<String, Object> gift = new HashMap<String, Object>();
        gift.put("skuId", skuId);
        gift.put("sendCount", sendCount);
        return gift;
    };
}
